fn main() {
    println!("Hello, struct!");

    let w = 30;
    let h = 40;
    println!("area1: {}.", area1(w, h));

    let r2 = Rect {
        width: 30,
        height: 40,
    };
    println!("area2: {}.", r2.area());

    let scale = 2;
    let r3 = Rect {
        width: dbg!(10 * scale),
        height: 15,
    };

    println!("rect3 is {:#?}", r3);
    println!("area3: {}.", r3.area());

    dbg!(&r2);
    dbg!(&r3);
    println!("can r2 hold r3? {}", r2.can_hold(&r3));

    let s1 = Rect::square(10);
    println!("squire: {:?}, area: {}", s1, s1.area());
}

fn area1(width: u32, height: u32) -> u32 {
    width * height
}

fn area2(dim: (u32, u32)) -> u32 {
    dim.0 * dim.1
}

#[derive(Debug)] // derive：attribute; Debug: trait
struct Rect {
    width: u32,
    height: u32,
}

impl Rect {
    fn area(&self) -> u32 {
        self.width * self.height
    }

    fn width(&self) -> bool {
        self.width > 0
    }

    fn can_hold(&self, other: &Rect) -> bool {
        self.width > other.width && self.height > other.height
    }

    fn square(size: u32) -> Rect {
        Rect {
            width: size,
            height: size,
        }
    }
}
